The environment JavaScript builds before it runs a single line of your function.
Every time a function is called, JavaScript creates an execution context for it — a self-contained environment holding that call's variables, its scope chain, and the value of this. There are really two phases to this: a creation phase, where variable and function declarations get hoisted and memory is allocated before any code runs, and an execution phase, where the code actually runs top to bottom and values get assigned.
These contexts don't exist in isolation — they stack. The global execution context sits at the bottom, and every function call pushes a new context onto the call stack, which gets popped off once the function returns. Each context also carries a reference to the context it was defined in (not called from), which is exactly what makes lexical scoping and closures work — a function can still reach variables from a context that's already been popped off the stack.
What you'll walk away knowing